﻿using System;

namespace JiShiBen.Core.DataStructure
{
	public enum HostType
	{
		Unspecified = -1,
		Host = 0,
		Working = 1
	}

	public struct Fragment : IEquatable<Fragment>
	{
		public static Fragment Empty = new Fragment(HostType.Unspecified, -1, -1);
		private readonly HostType _hostIndex;
		private long _offset;
		private long _length;

		public Fragment(HostType host, long offset, long length)
		{
			_hostIndex = host;
			_offset = offset;
			_length = length;
		}

		public HostType HostIndex
		{
			get { return _hostIndex; }
		}

		public long Offset
		{
			get { return _offset; }
		}

		public long LastIndex
		{
			get { return _offset + _length; }
		}

		public void SetLength(long length)
		{
			if (length < 0)
				throw new ArgumentOutOfRangeException("length", length, "Length must be a positive integral number.");

			_length = length;
		}

		public void SetOffset(long offset)
		{
			if (offset < 0)
				throw new ArgumentOutOfRangeException("offset", offset, "Offset must be a positive integral number.");

			_offset = offset;
		}

		public long Length
		{
			get { return _length; }
		}

		public bool Equals(Fragment other)
		{
			return other.HostIndex == HostIndex && other.Offset == Offset && other.Length == Length;
		}

		#region Operator Overloads

		public static bool operator ==(Fragment lhs, Fragment rhs)
		{
			return lhs.Equals(rhs);
		}

		public static bool operator !=(Fragment lhs, Fragment rhs)
		{
			return !lhs.Equals(rhs);
		}

		#endregion

		public override bool Equals(object obj)
		{
			if (ReferenceEquals(null, obj)) return false;
			return obj is Fragment && Equals((Fragment)obj);
		}

		public override int GetHashCode()
		{
			unchecked
			{
				var result = (int)HostIndex;
				result = (result * 397) ^ Offset.GetHashCode();
				result = (result * 397) ^ Length.GetHashCode();
				return result;
			}
		}
	}
}
